package com.sca.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sca.order.constant.RedisKeyConstant;
import com.sca.order.entity.Stock;
import com.sca.order.repository.StockMapper;
import com.sca.order.service.StockService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author liuxianfei
 * @since 2020/11/3 11:51
 */
@Slf4j
@Service
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements StockService {

    private final RedisTemplate<String, Object> redisTemplate;

    public StockServiceImpl(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean subtract(Long goodId, Integer num) {
        Stock stock = this.getOne(new LambdaQueryWrapper<Stock>().eq(Stock::getGoodId, goodId));
        if (stock != null) {
            int balance = stock.getNum() - num;
            if (num < 0) {
                balance = 0;
            }
            if (balance < 0) {
                return false;
            }
            Stock update = new Stock();
            update.setId(stock.getId());
            update.setVersion(stock.getVersion());
            update.setNum(balance);
            return this.updateById(update);
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addStock(Long goodId, Integer num, Integer type) {
        Stock stock = this.getOne(new LambdaQueryWrapper<Stock>().eq(Stock::getGoodId, goodId));
        if (stock != null) {
            if (type == 0) {
                // 更新redis中的库存，删除无库存的分布式锁
                redisTemplate.opsForValue().increment(RedisKeyConstant.ORDER_STR_SECKILL + goodId, num);
                redisTemplate.delete(RedisKeyConstant.STOCK_STR_LOCK);
                log.debug("回填库存成功！！");
                return true;
            } else if (type == 1) {
                int balance = stock.getNum() + num;
                Stock update = new Stock();
                update.setId(stock.getId());
                update.setVersion(stock.getVersion());
                update.setNum(balance);
                if (this.updateById(update)) {
                    redisTemplate.opsForValue().increment(RedisKeyConstant.ORDER_STR_SECKILL + goodId, num);
                    redisTemplate.delete(RedisKeyConstant.STOCK_STR_LOCK);
                    log.debug("增加库存成功！！");
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public Long decrStock(List<String> keys, Integer num) {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("/lua/stock.lua")));
        script.setResultType(Long.class);
        return redisTemplate.execute(script, keys, num);
    }

}
